package com.ruoyi.project.play.order.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.pay.domain.PayConfig;
import com.ruoyi.project.pay.service.IPayConfigService;
import com.ruoyi.project.play.order.domain.Order;
import com.ruoyi.project.play.order.service.IOrderService;
import com.ruoyi.tools.pay.controller.AbstractWxPayApiController;
import com.ruoyi.tools.pay.domain.WxPayBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单Controller
 * 
 * @author wyh
 * @date 2024-07-13
 */
@RestController
@RequestMapping("/play/order/api")
public class OrderApiController extends AbstractWxPayApiController
{
    @Autowired
    private IOrderService orderService;

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxPayBean wxPayBean;

    private String notifyUrl;
    private String refundNotifyUrl;
    private static final String USER_PAYING = "USERPAYING";

    @Autowired
    private IPayConfigService payConfigService;

    /**
     * 读取数据库支付配置
     * @return
     */
    @Override
    public WxPayApiConfig getApiConfig() {
        WxPayApiConfig apiConfig;

        PayConfig payConfig = new PayConfig();
        payConfig.setName("wechatPay");
        List<PayConfig> payConfigs = payConfigService.selectPayConfigList(payConfig);
        PayConfig pConfig = payConfigs.get(0);


        try {
            apiConfig = WxPayApiConfigKit.getApiConfig(pConfig.getAppid());
        } catch (Exception e) {
            apiConfig = WxPayApiConfig.builder()
                    .appId(pConfig.getAppid())
                    .mchId(pConfig.getMchId())
                    .partnerKey(pConfig.getCertPassword())
                    .certPath(pConfig.getCertPath())
                    .domain(pConfig.getNotifyPayDomain())
                    .build();
        }
        // 微信支付回调地址
        notifyUrl = apiConfig.getDomain().concat("/play/order/api/payNotify");
        // 微信退款回调地址
        refundNotifyUrl = apiConfig.getDomain().concat("/play/order/api/refundNotify");
        return apiConfig;
    }

    /**
     * 公众号支付
     */
    @PreAuthorize("@ss.hasPermi('play:order:add')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @RequestMapping(value = "/webPay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult webPay(HttpServletRequest request, @RequestParam("total_fee") String totalFee) {
        // openId，采用 网页授权获取 access_token API：SnsAccessTokenApi获取
        String openId = (String) request.getSession().getAttribute("openId");
        if (openId == null) {
            openId = "11111111";
        }

        if (StrUtil.isEmpty(openId)) {
            return AjaxResult.error("openId is null");
        }
        if (StrUtil.isEmpty(totalFee)) {
            return AjaxResult.error("请输入数字金额");
        }
        String ip = IpKit.getRealIp(request);
        if (StrUtil.isEmpty(ip)) {
            ip = "127.0.0.1";
        }

        WxPayApiConfig wxPayApiConfig = getApiConfig();

        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body("IJPay 让支付触手可及-公众号支付")
                .attach("Node.js 版:https://gitee.com/javen205/TNWX")
                .out_trade_no(WxPayKit.generateStr())
                .total_fee("1000")
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);
        log.info(xmlResult);

        Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            return AjaxResult.error(returnMsg);
        }
        String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            return AjaxResult.error(returnMsg);
        }

        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回

        String prepayId = resultMap.get("prepay_id");

        Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(),
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String jsonStr = JSON.toJSONString(packageParams);
        return AjaxResult.success(jsonStr);
    }

    /**
     * 异步通知
     * 这里面可以写判断支付成功之后的及具体业务需求
     */
    @RequestMapping(value = "/payNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String payNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        log.info("支付通知=" + xmlMsg);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);

        String returnCode = params.get("return_code");

        //通过支付订单号处理业务
        String transaction_id = params.get("transaction_id");
        log.info("支付订单号:"+transaction_id);

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, getApiConfig().getPartnerKey(), SignType.HMACSHA256)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                // 更新订单信息
                // 发送通知等
                Map<String, String> xml = new HashMap<String, String>(2);
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
                return WxPayKit.toXml(xml);
            }
        }
        return null;
    }


    /**
     * 查询订单列表
     */
    @PreAuthorize("@ss.hasPermi('play:order:list')")
    @GetMapping("/list")
    public AjaxResult list(Order order)
    {
        PageUtils.startPage();
        List<Order> list = orderService.selectOrderList(order);
        return AjaxResult.success(list);
    }


    /**
     * 获取订单详细信息
     */
    @PreAuthorize("@ss.hasPermi('play:order:query')")
    @GetMapping(value = "/{outTradeNo}")
    public AjaxResult getInfo(@PathVariable("outTradeNo") String outTradeNo)
    {
        return AjaxResult.success(orderService.selectOrderByOutTradeNo(outTradeNo));
    }

    /**
     * 新增订单
     */
    @PreAuthorize("@ss.hasPermi('play:order:add')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Order order)
    {
        orderService.insertOrder(order);

        return AjaxResult.success("新增成功");
    }

    /**
     * 修改订单
     */
    @PreAuthorize("@ss.hasPermi('play:order:edit')")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Order order)
    {
        orderService.updateOrder(order);
        return AjaxResult.success("更新成功");
    }

    /**
     * 删除订单
     */
    @PreAuthorize("@ss.hasPermi('play:order:remove')")
    @Log(title = "订单", businessType = BusinessType.DELETE)
	@DeleteMapping("/{outTradeNos}")
    public AjaxResult remove(@PathVariable String[] outTradeNos)
    {
        orderService.deleteOrderByOutTradeNos(outTradeNos);
        return AjaxResult.success("删除成功");
    }
}
